﻿using IdentityModel;
using IdentityModel.Client;
using IdentityServer4.Models;
using IdentityServer4.Validation;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Security.Claims;
using System.Threading.Tasks;
using YSC_Core.BLL.Domain.Entity;
using YSC_Core.BLL.Domain.Utils;

namespace IdentityServer.OAuth
{
    public class ResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator
    {
        private readonly IHttpClientFactory _httpClientFactory;
        public ResourceOwnerPasswordValidator(IHttpClientFactory httpClientFactory)
        {
            _httpClientFactory = httpClientFactory;
        }
        public async Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
        {
            try
            {
                var client = _httpClientFactory.CreateClient();

                //已过时
                //  DiscoveryResponse disco = await DiscoveryClient.GetAsync("http://localhost:5000");
                //  TokenClient tokenClient = new TokenClient(disco.TokenEndpoint, "AuthServer", "secret");
                //  var tokenResponse = await tokenClient.RequestClientCredentialsAsync("api1");

                //DiscoveryResponse disco = await client.GetDiscoveryDocumentAsync("http://localhost:5000");
                //var tokenResponse = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest
                //{
                //    Address = disco.TokenEndpoint,
                //    ClientId = "AuthServer",
                //    ClientSecret = "secret",
                //    Scope = "api1"
                //});
                //if (tokenResponse.IsError)
                //    throw new Exception(tokenResponse.Error);

                //client.SetBearerToken(tokenResponse.AccessToken);
                //   RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(10000).setConnectTimeout(10000).build();


                //http://localhost:5001/api/User/GetOAuthUser?userName=1&passWord=1
                //http://yscoauth.cnfm.com.cn:8099
               
                client.Timeout = TimeSpan.FromSeconds(60);
                var response = await client.GetAsync("http://localhost:5001/api/User/GetOAuthUser?userName=" + context.UserName + "&passWord=" + context.Password);
                // var response = await client.GetAsync("https://fishopeni.cnfm.com.cn:8095/api/User/GetOAuthUser?userName=" + context.UserName + "&passWord=" + context.Password);



                if (!response.IsSuccessStatusCode)
                {
                    throw new Exception("Resource server is not working!");
                }
                else
                {
                    var content = await response.Content.ReadAsStringAsync();
                    YscUser user = JsonConvert.DeserializeObject<YscUser>(content);
                    //get your user model from db (by username - in my case its email)                  
                    if (user != null)
                    {
                        //check if password match - remember to hash password if stored as hash in db
                        if (user.Password == context.Password)
                        {
                            context.Result = new GrantValidationResult(
                             user.Id.ToString() ?? throw new ArgumentException("Subject ID not set", nameof(user.Id)),
                             OidcConstants.AuthenticationMethods.Password, GetUserClaims(user),
                             user.UserName);

                            return;
                        }
                        context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "Incorrect password");
                        return;
                    }
                    context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "User does not exist.");
                    return;
                }
            }
            catch (Exception ex)
            {

            }
        }

        public static Claim[] GetUserClaims(YscUser user)
        {
            return new Claim[]
                {
             new Claim("user_id", user.Id.ToString() ?? ""),
             new Claim(JwtClaimTypes.Name, (!string.IsNullOrEmpty(user.UserName) && !string.IsNullOrEmpty(user.Phone)) ? user.UserName  : ""),
                    //new Claim(JwtClaimTypes., user.Firstname  ?? ""),
                    //new Claim(JwtClaimTypes.FamilyName, user.Lastname  ?? ""),
                    //new Claim(JwtClaimTypes.Email, user.Email  ?? ""),
                    //new Claim("some_claim_you_want_to_see", user.Some_Data_From_User ?? ""),  

                    //roles  
                     new Claim(JwtClaimTypes.Role,  user.UserName,"role")
                };

            //List<Claim> claims = new List<Claim>();
            //Claim claim;
            //claim = new Claim("id", user.Id);
            //claims.Add(claim);
            //return claims.ToArray();
        }
    }
}
